using Oracle.ManagedDataAccess.Client;
using System.Diagnostics;
using System.Collections.Concurrent;
using Microsoft.Extensions.Logging;
using System.Data;

namespace Lzfy_His_Service.Services
{
    /// <summary>
    /// 连接泄漏检测器 - 基于DbHelperHisBi模式
    /// 监控连接生命周期，检测潜在泄漏
    /// </summary>
    public class ConnectionLeakDetector : IDisposable
    {
        private readonly ILogger<ConnectionLeakDetector> _logger;
        private readonly ConcurrentDictionary<string, ConnectionInfo> _activeConnections;
        private readonly Timer _cleanupTimer;
        private readonly TimeSpan _warningThreshold = TimeSpan.FromSeconds(30);
        private readonly TimeSpan _criticalThreshold = TimeSpan.FromMinutes(5);

        public ConnectionLeakDetector(ILogger<ConnectionLeakDetector> logger)
        {
            _logger = logger;
            _activeConnections = new ConcurrentDictionary<string, ConnectionInfo>();
            _cleanupTimer = new Timer(CleanupExpiredConnections, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
        }

        /// <summary>
        /// 注册新连接
        /// </summary>
        public IDisposable RegisterConnection(OracleConnection connection, string operation)
        {
            var connectionId = Guid.NewGuid().ToString();
            var info = new ConnectionInfo
            {
                ConnectionId = connectionId,
                Connection = new WeakReference(connection),
                Operation = operation,
                CreatedAt = DateTime.Now,
                StackTrace = Environment.StackTrace
            };

            _activeConnections[connectionId] = info;
            
            return new ConnectionTracker(connectionId, this);
        }

        /// <summary>
        /// 注销连接
        /// </summary>
        public void UnregisterConnection(string connectionId)
        {
            _activeConnections.TryRemove(connectionId, out _);
        }

        /// <summary>
        /// 获取连接统计信息
        /// </summary>
        public ConnectionStats GetConnectionStats()
        {
            var now = DateTime.Now;
            var activeConnections = _activeConnections.Values.ToList();

            return new ConnectionStats
            {
                TotalActive = activeConnections.Count,
                WarningCount = activeConnections.Count(c => now - c.CreatedAt > _warningThreshold),
                CriticalCount = activeConnections.Count(c => now - c.CreatedAt > _criticalThreshold),
                OldestConnection = activeConnections.Any() ? 
                    activeConnections.Min(c => c.CreatedAt) : DateTime.MinValue,
                Operations = activeConnections.Select(c => c.Operation).ToList()
            };
        }

        /// <summary>
        /// 清理过期连接记录
        /// </summary>
        private void CleanupExpiredConnections(object? state)
        {
            var expiredConnections = _activeConnections
                .Where(kv => kv.Value.Connection.Target == null || 
                            (kv.Value.Connection.Target as OracleConnection)?.State == System.Data.ConnectionState.Closed)
                .ToList();

            foreach (var kv in expiredConnections)
            {
                _activeConnections.TryRemove(kv.Key, out _);
            }
        }

        /// <summary>
        /// 获取清理建议
        /// </summary>
        public List<string> GetCleanupRecommendations()
        {
            var stats = GetConnectionStats();
            var recommendations = new List<string>();

            if (stats.CriticalCount > 0)
            {
                recommendations.Add($"发现 {stats.CriticalCount} 个严重连接泄漏，需要立即处理");
                recommendations.Add("建议检查长时间运行的操作，确保连接正确释放");
                recommendations.Add("考虑使用 using 语句自动释放连接");
            }
            else if (stats.WarningCount > 0)
            {
                recommendations.Add($"发现 {stats.WarningCount} 个潜在连接泄漏");
                recommendations.Add("建议监控连接使用情况");
            }
            else
            {
                recommendations.Add("连接使用正常，无泄漏风险");
            }

            return recommendations;
        }

        public void Dispose()
        {
            _cleanupTimer?.Dispose();
            _activeConnections.Clear();
        }

        private class ConnectionTracker : IDisposable
        {
            private readonly string _connectionId;
            private readonly ConnectionLeakDetector _detector;

            public ConnectionTracker(string connectionId, ConnectionLeakDetector detector)
            {
                _connectionId = connectionId;
                _detector = detector;
            }

            public void Dispose()
            {
                _detector.UnregisterConnection(_connectionId);
            }
        }

        private class ConnectionInfo
        {
            public string ConnectionId { get; set; } = string.Empty;
            public WeakReference Connection { get; set; } = default!;
            public string Operation { get; set; } = string.Empty;
            public DateTime CreatedAt { get; set; }
            public string StackTrace { get; set; } = string.Empty;
        }

        public class ConnectionStats
        {
            public int TotalActive { get; set; }
            public int WarningCount { get; set; }
            public int CriticalCount { get; set; }
            public DateTime OldestConnection { get; set; }
            public List<string> Operations { get; set; } = new List<string>();
        }
    }

    /// <summary>
    /// 连接管理扩展方法
    /// </summary>
    public static class ConnectionExtensions
    {
        public static IDisposable TrackConnection(this OracleConnection connection, 
            ConnectionLeakDetector detector, string operation, string? operationId = null)
        {
            var fullOperation = string.IsNullOrEmpty(operationId) 
                ? operation 
                : $"{operation} [{operationId}]";
            return detector.RegisterConnection(connection, fullOperation);
        }
    }
}